package sk.marek.barak.client;


import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;


import sk.marek.barak.shared.LoggedInUserServiceFactory;
import sk.marek.barak.shared.LoginServiceFactory;
import sk.marek.barak.shared.ThoughtServiceFactory;
import sk.marek.barak.shared.TokenServiceFactory;
import sk.marek.barak.shared.UserInformationServiceFactory;


import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.ScrollEvent;
import com.google.gwt.event.dom.client.ScrollHandler;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PushButton;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */

public class ShareLife implements EntryPoint {
	private static Label logo;
	private FlexTable chatTable;
	private FlexTable userTable;
	private FlexTable storyTable;
	private Map<String,String> loggedInUSers;
	private JustEmpty empty;
	private JustEmpty menubar;
	private JustEmpty logoutBar;
	private TokenServiceAsync tokenService;
	private DockPanel middlePanel;
	private static List<String> openChat;
	
	private ScrollPanel storyScroolPanel;
	private DockLayoutPanel mainPanel;
	
	private static UserInformation curentUser;
	
	private PushButton profile;
	private Composite shownUser;
	
	private ThoughtServiceAsync thoughtService;
	private LoginServiceAsync loginService;
	private LoginInfo loginInfo;
	private LoggedInUserServericeAsync loggedIn;
	private VerticalPanel newThoughtPanel;
	
	
	
	@Override
	public void onModuleLoad() {
		loginService = LoginServiceFactory.getLoginService();
		loginService.login(GWT.getHostPageBaseURL(), new AsyncCallback<LoginInfo>() {

			@Override
			public void onFailure(Throwable caught) {
				Window.alert("Login failed");
				
			}

			@Override
			public void onSuccess(LoginInfo result) {
				loginInfo = result;
				if(loginInfo.getLogedIn()){
					UserInfomationServiceAsync userInfoService = UserInformationServiceFactory.getUserInformationService();
					userInfoService.getCurentUserInformation(new AsyncCallback<UserInformation>() {
						
						@Override
						public void onSuccess(UserInformation result) {
							signedIn(result);
						}
						
						@Override
						public void onFailure(Throwable caught) {
							Window.alert("Error loading your information has failed");
							
						}
					});
				}
				else
					loadLogin();
			}
		});
		
	}

	/**
	 * @wbp.parser.entryPoint
	 */
	private void signedIn(UserInformation info) {
		loggedIn = LoggedInUserServiceFactory.getLoggedInUserService();
		loggedIn.loggedIn(new AsyncCallback<Void>() {

			@Override
			public void onFailure(Throwable caught) {
				Window.alert("Failed to logg in");
				
			}

			@Override
			public void onSuccess(Void result) {
				loadAllUsers();
				getUserThoughts();
				
				
			}
			
		});
		curentUser = info;
		userTable = new FlexTable();
		chatTable = new FlexTable();
		storyTable = new FlexTable();
		
		userTable.setCellSpacing(0);
		
		chatTable.setCellSpacing(12);
		
		mainPanel = new DockLayoutPanel(Unit.EM);
		DockPanel headerPanel = new DockPanel();
		headerPanel.setStyleName("headerPanel");
		headerPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
		profile = new PushButton("Profile");
		profile.addClickHandler(new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				showUserProfile();
				
				
			}
		});
		logo = new Label("Share-Life");
		logo.setSize("113px", "30px");
		logo.setStyleName("logo");
		
		headerPanel.add(logo,DockPanel.WEST);
		menubar = new JustEmpty();
		menubar.setWidth("55px");
		logoutBar = new JustEmpty();
		
		headerPanel.add(menubar,DockPanel.WEST);
		headerPanel.add(profile,DockPanel.CENTER);
	
		
		Anchor logOut = new Anchor("Log out");
		logOut.setHref(loginInfo.getLogoutUrl());
		logOut.addClickHandler(new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				userLogout();
				loadLogin();
				
			}
		});
		
		headerPanel.add(logOut,DockPanel.EAST);
		headerPanel.add(logoutBar,DockPanel.EAST);
		
		mainPanel.addNorth(headerPanel,3);
	
		resizeLogout();
		
		
		
		RootLayoutPanel rootLayoutPanel = RootLayoutPanel.get();
		rootLayoutPanel.clear();
		
		rootLayoutPanel.add(mainPanel);
		rootLayoutPanel.setWidgetLeftRight(mainPanel, 0.0, Unit.PX, 0.0, Unit.PX);
		mainPanel.addStyleName("dockPanelBorder");	
	
		
		ScrollPanel userPanel = new ScrollPanel();
		userPanel.setAlwaysShowScrollBars(false);
		userPanel.add(userTable);
		
		ScrollPanel chatPanel = new ScrollPanel();
				chatPanel.add(chatTable);
				chatPanel.addScrollHandler(new ScrollHandler() {
					
					@Override
					public void onScroll(ScrollEvent event) {
						resetChatWindows();
						
					}
				});
				
		mainPanel.addWest(userPanel, 12.4);
		
		mainPanel.addSouth(chatPanel, 3.5);
		userPanel.setStyleName("gwt-ScrollPanel");
		
		
		middlePanel = new DockPanel();
		middlePanel.setStyleName("centerPanel");
		this.empty = new JustEmpty();
		
		
		newThoughtPanel= new VerticalPanel();
		newThoughtPanel.setSize("285px", "50px");
		final TextArea text = new TextArea();
		text.setSize("285px", "50px");
		text.addStyleName("richTable");
		newThoughtPanel.add(text);
		PushButton btnPost = new PushButton("Share");
		btnPost.setSize("70px", "20px");
		newThoughtPanel.add(btnPost);
		btnPost.addClickHandler(new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				if(!"".equals(text.getText())){
					if(thoughtService==null)
						thoughtService = ThoughtServiceFactory.getThoughtService();
					
					thoughtService.saveThought(text.getText(), new AsyncCallback<UserThought>() {

						@Override
						public void onFailure(Throwable caught) {
							Window.alert("Sharing failed");
							
						}

						@Override
						public void onSuccess(UserThought result) {
							addUserThought(result);
							text.setText("");
							
						}
					});
					
				}
					
			}});
		
		
			
		storyTable.setWidget(0,0,newThoughtPanel);
		storyScroolPanel = new ScrollPanel();
		storyScroolPanel.add(storyTable);
		
		
		middlePanel.add(storyScroolPanel,DockPanel.WEST);
		middlePanel.add(empty,DockPanel.CENTER);
		mainPanel.add(middlePanel);
		storyScroolPanel.setHeight(String.valueOf(Window.getClientHeight()-70)+"px");
		storyScroolPanel.setWidth(String.valueOf(storyScroolPanel.getOffsetWidth()+30)+"px");
		
		Window.addResizeHandler(new ResizeHandler() {
			
			@Override
			public void onResize(ResizeEvent event) {
			storyScroolPanel.setHeight(String.valueOf(Window.getClientHeight()-70)+"px");
			resetChatWindows();
			setDistance();
			resizeLogout();
			}});
	Timer timer = new Timer(){

		@Override
		public void run() {
			loadAllUsers();
			checkForToken();
			
		}
		
		
	};
	
	
	timer.scheduleRepeating(10000);
	Window.addCloseHandler(new CloseHandler<Window>() {
		
		@Override
		public void onClose(CloseEvent<Window> event) {
			userLogout();
		}
			
	});
		
	
	Timer thoughtTimer = new Timer(){
		@Override
		public void run() {
			getUserThoughts();
			
		}
	};
	thoughtTimer.scheduleRepeating(60000);
	
}
	
	public void resetChatWindows() {
		Iterator<Widget> itr =chatTable.iterator();
			while(itr.hasNext()){
				UserTab tab =((UserTab)itr.next());
				tab.resetChatLocation();
				if(tab.getAbsoluteLeft()<160)
					tab.closeChat();
				if(tab.getAbsoluteLeft()+tab.getOffsetWidth()>Window.getClientWidth())
					tab.closeChat();
			}
			
	}
	private void loadAllUsers(){
		loggedIn.getLoogedInUsers(new AsyncCallback<List<UserInformation>>() {

			@Override
			public void onFailure(Throwable caught) {
				
				
			}

			@Override
			public void onSuccess(List<UserInformation> result) {
				addAllUsers(result);
				
			}
		
		});
		
	}
	
	private void addAllUsers(List<UserInformation> users){
		userTable.removeAllRows();
		
		for(final UserInformation user : users){
			if(loggedInUSers==null)
				loggedInUSers=new HashMap<String, String>();
			if(!loggedInUSers.containsKey(user.getUserID()))
				loggedInUSers.put(user.getUserID(),user.getName());
			
			if(user.getUserID().equals(curentUser.getUserID()))
				continue;
			
			Label usr = new Label(user.getName());
			usr.setWidth("100px");
			usr.addClickHandler(new ClickHandler() {
				
				@Override
				public void onClick(ClickEvent event) {
					addUserChat(user.getName(), user.getUserID());
				}
			});
			
			Button userInfo = new Button("->");
			userInfo.setStyleName("showUser");
			userInfo.addClickHandler(new ClickHandler() {
				
				@Override
				public void onClick(ClickEvent event) {
					showUserInfo(user);
					
					
				}
			});
	
			int row = userTable.getRowCount();
			userTable.setWidget(row,0, usr);
			userTable.setWidget(row,1,userInfo);
			
		}
		
	}
	private void addUserChat(String name,String id){
		
		Iterator<Widget> iterator = chatTable.iterator();
		UserTab tmp =new UserTab(name,id,chatTable);
		if(!iterator.hasNext())
			chatTable.setWidget(0, 0,tmp);
		
		else{
			while(iterator.hasNext()){
				if(((UserTab)iterator.next()).getUserID().equals(tmp.getUserID()))
					return;
			}
			chatTable.setWidget(0, chatTable.getCellCount(0),tmp);
			
		
		}
	}
	
	private void setDistance(){
		int actual = (Window.getClientWidth() - 355) - empty.getAbsoluteLeft() ;
		String width;
		if(actual<0)
			width = "0px";
		else
			width = String.valueOf(actual)+"px";
	empty.setWidth(width);
	}
	
	
	private void showUserInfo(UserInformation user){
		if(shownUser!=null)
			middlePanel.remove(shownUser);
		
		shownUser=new UserProfileUI(user);
		shownUser.setStyleName("profile");
		shownUser.setWidth("350px");
		middlePanel.add(shownUser,DockPanel.EAST);
		setDistance();
	}
	
	private void resizeLogout(){
		
		int size =Window.getClientWidth()-272;
		if(size<0)
			size = 0;
		logoutBar.setWidth(String.valueOf(size)+"px");
	}
	private void showUserProfile(){
		if(shownUser!=null)
			middlePanel.remove(shownUser);
		
		shownUser = new UserProfile();
		shownUser.setWidth("350");
		shownUser.setStyleName("profile");
		middlePanel.add(shownUser,DockPanel.EAST);
		setDistance();

	}
	
	private void loadLogin(){
		VerticalPanel panel= new VerticalPanel();
		Label loginLabel = new Label("Please login to your Google acount to access the Share-Life social network");
		Anchor singInLink = new Anchor("Sign in");
		singInLink.setHref(loginInfo.getLoginUrl());
		panel.add(loginLabel);
		panel.add(singInLink);
		RootLayoutPanel.get().clear();
		RootLayoutPanel.get().add(panel);
		
	
		
	}
	public static UserInformation getCurentUser(){
		return curentUser;
	}
	
	private void addUserThought(UserThought thought){
	storyTable.insertRow(1);
	storyTable.setWidget(1, 0, new ThoughtUI(thought));
	};
	
	private void userLogout(){
		loggedIn.loggedOut(new AsyncCallback<Void>() {

			@Override
			public void onFailure(Throwable caught) {
			
				
			}

			@Override
			public void onSuccess(Void result) {
				// TODO Auto-generated method stub
				
			}
		
		});
	}
	private void checkForToken(){
		if(tokenService==null)
			tokenService = TokenServiceFactory.getTokenService();
		tokenService.getTokens(new AsyncCallback<List<String>>() {

			@Override
			public void onFailure(Throwable caught) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void onSuccess(List<String> result) {
				if(result!=null){
					if(openChat==null)
						openChat = new ArrayList<String>();
					for(String user : result){
						if(!openChat.contains(user)){
							openChat.add(user);
							addUserChat(loggedInUSers.get(user), user);
						}
					}
				}
				
			}
		
		});
	}
	private void getUserThoughts(){
		if(thoughtService==null)
			thoughtService = ThoughtServiceFactory.getThoughtService();
		if(loggedInUSers!=null){
			thoughtService.getUsersThought(new ArrayList<String>(loggedInUSers.keySet()), new AsyncCallback<List<UserThought>>() {

				@Override
				public void onFailure(Throwable caught) {
					// TODO Auto-generated method stub
					
				}

				@Override
				public void onSuccess(List<UserThought> result) {
					Collections.sort(result);
					for(int i = 0;i<result.size();i++){
						storyTable.setWidget(i+1, 0, new ThoughtUI(result.get(i)));
					};
					if(storyTable.getRowCount()>result.size()+1){
						for(int i = result.size()+1;i<storyTable.getRowCount();i++)
							storyTable.removeRow(i);
					}
						
					
				}
			
			});
		}
	}
	public static List<String> getChatList(){
		return openChat;
	}
	
	
}
